package uk.co.agileworks.bidpirate.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import uk.co.agileworks.bidpirate.model.Bid;
import uk.co.agileworks.bidpirate.model.Item;
import uk.co.agileworks.bidpirate.model.Status;
import uk.co.agileworks.bidpirate.model.User;
import uk.co.agileworks.bidpirate.web.UserSession;

@Service
public class BusinessFacadeImpl implements BusinessFacade {

	@Autowired
	private DAO dao;

	@Autowired
	private UserSession userSession;

	@Transactional
	@Override
	public void addBid(Bid bid) {
		bid.setStatus(userSession.isLoggedIn() ? Status.ACTIVE : Status.NOT_ACTIVE);
		dao.saveOrUpdateBid(bid);
		dao.saveOrUpdateItem(bid.getItem());
		dao.saveOrUpdateUser(bid.getUser());
	}

	@Transactional
	@Override
	public void createAccount(User guest) {

		if (dao.getUser(guest.getUsername()) != null) {
			throw new ServiceException("username.exists");
		}
		guest.setId(userSession.getUser().getId());
		dao.saveOrUpdateUser(guest);
		for (Bid bid : listBids(guest)) {
			bid.setStatus(Status.ACTIVE);
		}
		userSession.logIn(guest);

	}

	@Transactional
	@Override
	public void deleteBid(long id) {
		Bid bid = dao.getBid(id);
		dao.deleteBid(bid);
	}

	@Transactional(readOnly = true)
	@Override
	public Set<String> getAlerts(List<Bid> bids) {
		Set<String> alerts = new HashSet<String>();
		for (Bid bid : bids) {
			if (bid.getStatus() == Status.NOT_ACTIVE) {
				alerts.add("alert.not.active");
			}
		}
		return alerts;
	}

	@Transactional(readOnly = true)
	@Override
	public List<Bid> listBids(User user) {
		List<Bid> bids = new ArrayList<Bid>();
		if (user.getId() != null) {
			bids = dao.getBids(user);
		}
		return bids;
	}

	@Transactional
	@Override
	public void logIn(User guest) {
		User user = dao.getUser(guest.getUsername());
		if (user == null || !user.getPassword().equals(guest.getPassword())) {
			throw new ServiceException("login.invalid");
		}
		guest.setId(userSession.getUser().getId());
		for (Bid bid : listBids(guest)) {
			bid.setStatus(Status.ACTIVE);
			bid.setUser(user); // TODO already bid on item
		}
		userSession.logIn(user);
	}

	@Transactional
	@Override
	public void updateAccount(User user) {
		user.setId(userSession.getUser().getId());
		dao.saveOrUpdateUser(user);
		userSession.logIn(user);
	}

	@Transactional(readOnly = true)
	@Override
	public Bid getBid(long id) {
		return dao.getBid(id);
	}

	@Transactional
	@Override
	public void editBid(Bid bid) {
		dao.saveOrUpdateBid(bid);
	}

	@Transactional
	@Override
	public void updatePrice(long itemNumber, double price) {
		Item item = dao.getItem(itemNumber);
		item.setPrice(price);
		dao.saveOrUpdateItem(item);
	}

}
